#!/usr/bin/env python
# encoding: utf-8
# @author: Lin Han
# @contact: voldemort22@126.com
# @file: deprecated_app.py
# @time: 2021/3/23 15:33
# @desc:
import json
from typing import Optional, List

from fastapi import APIRouter, File, UploadFile, Request, BackgroundTasks

from application.history_clamp.crud import keyword_search_history_clamp, generate_history_clamp_data
from application.history_clamp.queryModels import UploadHistoryClampModel
from background.crud import extract_history_clamp_from_mongo_to_redis
from models.queryModels import MultipleConditionQueryHistoryClamps, LockFlagQuery, UpdateHistoryClampConfigData, UpdateHistoryClamp
from models.responseModels import ResponseDict
from utils.mongo_tools import update_mongo_value, retrieve_all_mongo_values, create_one_mongo_value, retrieve_one_mongo_value, delete_mongo_value, history_clamp_number_generator
from utils.utils import create_folder, write_file, create_folder_including_workpiece
from views.configs import *
from views.crud import upload_to_aliyun_clamp_model, separate_page, send_to_message_queue, calculate_page

deprecated_history_clamp_router = APIRouter(
    # prefix="/api/first",
    prefix="/api/history_clamp",
    tags=["history_clamp"],
)


@deprecated_history_clamp_router.post("/v1/history_clamps", response_model=ResponseDict)
async def multiple_condition_query_history_clamps(request: Request, queryModel: MultipleConditionQueryHistoryClamps):
    """
    列表查询多条历史夹具。输入参数所有字段均可为空。

    - :param queryModel: 该对象包含isFlag, isFeature以及可为空的厂家标准standard
    - :return:
    """
    model = {"data": {"result": []}}
    result = []
    # 先把redis中的符合历史夹具的key都拿出来
    history_clamp_number_list = await request.app.state.redis.get("history_clamp")
    history_clamp_number_list = json.loads(history_clamp_number_list)
    # 用上面的number列表去redis中查询所有历史夹具
    for i in history_clamp_number_list:
        temp_item = await request.app.state.redis.get(i)
        if temp_item == None:
            # 去mongo中查询这个id的数据
            temp_result = retrieve_one_mongo_value(i, database_name=MONGO_DATABASE_NAME, collection_name=HISTORY_CLAMP_COLLECTION)
            # 如果mongo里能查到这条数据再把它更新到redis中
            if len(temp_result) > 0:
                temp_item = temp_result[0]
                # 把mongo中查到的数据set到redis数据库中
                await request.app.state.redis.set(temp_item["number"], json.dumps(temp_item))
            else:
                # 若是走到这一步那说明不但redis里没有，连mongo里面也没有这个number的数据了，就跳过append吧
                continue
        else:
            temp_item = json.loads(temp_item)
        result.append(temp_item)

    result = keyword_search_history_clamp(queryModel, result)
    model["data"]["total"] = len(result)
    if len(result) > 0:
        # 如果isTotal为True，意味着进入了详情页面，则不需要分页了。
        if not queryModel.isTotal:
            model["data"]["result"] = separate_page(result, page=queryModel.page, pagesize=queryModel.pagesize)
        else:
            model["data"]["result"] = result
    model["status"] = 1
    return model


@deprecated_history_clamp_router.post("/v1/history_clamp_catia_file")
async def upload_history_clamp_catia_file(request: Request, workpieceFile: Optional[UploadFile] = File(None), clampFile: UploadFile = File(...)):
    """
    这里接收用户上传的历史夹具模型文件，返回上传是否成功，以及上传的文件唯一id（number）和文件名。

    - :param workpiece_file: 工件Catia模型，可为空
    - :param clamp_file: 夹具Catia模型，必填项
    - :return:
    """
    # 初始化必要信息
    isFeature: bool = False
    isFlag: bool = False
    version = "2.0"
    desc = "这是历史夹具"
    folder = create_folder()
    clamp_file_path = f"{folder}/{clampFile.filename}"
    # 写入文件
    write_file(file_path=clamp_file_path, file=clampFile)
    workpiece_file_path = None
    if workpieceFile is not None:
        workpiece_folder = create_folder_including_workpiece()
        workpiece_file_path = f"{workpiece_folder}/{workpieceFile.filename}"
        write_file(file_path=workpiece_file_path, file=workpieceFile)

    # try:
    # 上传至阿里云
    clampModel = upload_to_aliyun_clamp_model(
        filename=clamp_file_path,
        workpiece_file_path=workpiece_file_path,
        desc=desc,
        version=version,
        isFeature=isFeature,
        isFlag=isFlag,
    )
    await request.app.state.redis.set(clampModel["number"], json.dumps(clampModel))
    # TODO: 这里有个坑，上传的数据只有catpart文件的S3地址，gltf文件的地址要过一段时间消息队列中转化完成后才会补进来。而redis的数据这里就直接生成了，那么缓存里的数据就没有gltf的信息了。这里我建议中短期的做法是message_queue的那个接口也要跟着mongo的数据一起更新。
    create_one_mongo_value(
        clampModel,
        database_name=MONGO_DATABASE_NAME,
        collection_name=HISTORY_CLAMP_COLLECTION,
    )

    model = {"data": clampModel["number"], "status": 1}
    return model



@deprecated_history_clamp_router.get("/v1/workpiece_gltf_file")
async def get_workpiece_gltf_file(number: str):
    """
    Deprecated.
    返回工件的gltf模型在OSS上的地址

    - :param number: 该工件对应的夹具（注意是夹具，不是工件，工件自己没有number）的number
    - :return:
    """
    model = {"data": ""}
    original_data = retrieve_one_mongo_value(number, database_name=MONGO_DATABASE_NAME, collection_name=HISTORY_CLAMP_COLLECTION)
    try:
        model["data"] = original_data[0]["file"][WORKPIECE_GLTF_OSS_ADDRESS]
    except:
        model["status"] = 0
    model["status"] = 1
    return model


@deprecated_history_clamp_router.get("/v1/history_clamp_config")
async def retrieve_history_clamp_config(request: Request):
    """
    查询历史夹具配置表里的信息。

    - :return:
    """
    try:
        configData = await request.app.state.redis.get("history_clamp_config")
        configData = json.loads(configData)
    except:
        configData = retrieve_all_mongo_values(
            {"type": "clamp"},
            collection_name="config"
        )[0]['configData']
        # 把mongo中查到的数据set到redis数据库中
        await request.app.state.redis.set("history_clamp_config", json.dumps(configData))

    model = {"data": configData, "status": 1}

    return model


@deprecated_history_clamp_router.put("/v1/history_clamp_flag_tag")
async def update_history_clamp_flag_tag(request: Request, queryModel: LockFlagQuery):
    """
    锁定夹具状态

    - :param queryModel: 该类包含夹具的唯一编码number以及布尔类型字段isFlag
    - :return:
    """
    # First delete the corresponded data in redis.
    try:
        await request.app.state.redis.delete(queryModel.number)
    except:
        pass

    update_mongo_value(
        filter_condition={"number": queryModel.number},
        new_value={"$set": {"isFlag": queryModel.isFlag}},
        database_name=MONGO_DATABASE_NAME,
        collection_name=HISTORY_CLAMP_COLLECTION,
    )

    original_data = retrieve_one_mongo_value(queryModel.number, database_name=MONGO_DATABASE_NAME, collection_name=HISTORY_CLAMP_COLLECTION)[0]
    await request.app.state.redis.set(queryModel.number, json.dumps(original_data))

    model = {
        "status": 1,
        "data": True,
    }
    return model


@deprecated_history_clamp_router.get("/v1/history_clamp_drop_down_box", response_model=ResponseDict)
async def get_history_clamp_drop_down_box(request: Request):
    """
    ## 历史夹具下拉框数据。
    - 注意原来是POST，现在改为GET了。
    - 查询历史夹具配置表里的信息。

    - :return:
    """
    # 先把redis中的符合历史夹具的key都拿出来
    try:
        config_data = await request.app.state.redis.get("history_clamp_config")
        config_data = json.loads(config_data)
    except:
        config_data = retrieve_all_mongo_values(
            {"type": "clamp"},
            collection_name="config",
        )[0]['configData']
        # 把mongo中查到的数据set到redis数据库中
        await request.app.state.redis.set("history_clamp_config", json.dumps(config_data))

    model = {"data": config_data, "status": 1}
    return model


@deprecated_history_clamp_router.delete("/v1/history_clamp")
async def delete_history_clamp(request: Request, number: str):
    """
    删除一套夹具数据。

    - :param number: 夹具的number
    - :return:
    """
    try:
        await request.app.state.redis.delete(number)
    except:
        pass

    model = {"data": False}
    try:
        result = delete_mongo_value(number, database_name=MONGO_DATABASE_NAME, collection_name=HISTORY_CLAMP_COLLECTION)
        if result.deleted_count > 0:
            model["data"] = True
            model["status"] = 1
        else:
            model["status"] = 0
    except:
        model["status"] = 0
    return model


@deprecated_history_clamp_router.put("/v1/history_clamp")
async def update_history_clamp(request: Request, queryModel: UpdateHistoryClamp):
    """
    更新历史夹具模型表里每个模型的Tag属性。

    - :param queryModel:
    - :return:
    """

    tag = retrieve_all_mongo_values(
        {"number": queryModel.number},
        database_name=MONGO_DATABASE_NAME,
        collection_name=HISTORY_CLAMP_COLLECTION,
    )[0]['tag']
    if queryModel.area is not None:
        tag['area'] = queryModel.area
    if queryModel.hasPin is not None:
        tag['hasPin'] = queryModel.hasPin
    if queryModel.hasStopBlock is not None:
        tag['hasStopBlock'] = queryModel.hasStopBlock
    if queryModel.rpsNumber is not None:
        tag['rpsNumber'] = queryModel.rpsNumber
    if len(queryModel.standard) > 0:
        tag['standard'] = queryModel.standard
    if len(queryModel.rpsType) > 0:
        tag['rpsType'] = queryModel.rpsType
    if len(queryModel.elseTag) > 0:
        tag['elseTag'] = queryModel.elseTag
    if len(queryModel.pinType) > 0:
        tag['pinType'] = queryModel.pinType
    if queryModel.airNumber is not None:
        tag['airNumber'] = queryModel.airNumber
    if queryModel.hasSensor is not None:
        tag['hasSensor'] = queryModel.hasSensor
    if queryModel.hasSucker is not None:
        tag['hasSucker'] = queryModel.hasSucker
    updateInfo = {"$set": {"tag": tag}}
    update_mongo_value(
        {"number": queryModel.number},
        updateInfo,
        database_name=MONGO_DATABASE_NAME,
        collection_name=HISTORY_CLAMP_COLLECTION,
    )

    try:
        original_data = retrieve_one_mongo_value(queryModel.number, database_name=MONGO_DATABASE_NAME, collection_name=HISTORY_CLAMP_COLLECTION)[0]
        await request.app.state.redis.set(queryModel.number, json.dumps(original_data))
    except:
        pass

    model = {"data": True, "status": 1}
    return model


@deprecated_history_clamp_router.get("/v1/history_clamp")
async def retrieve_history_clamp(request: Request, number: str):
    """
    ##返回一条历史夹具的完整信息
    Deprecated.

    - :param number: 编号
    - :return:
    """
    model = {"data": {}}

    # take out the data in redis
    try:
        try:
            history_clamp = await request.app.state.redis.get(number)
            data = json.loads(history_clamp)
        except:
            # if reach here then means no data in redis. Now go to mongo.
            data = retrieve_one_mongo_value(number, database_name=MONGO_DATABASE_NAME, collection_name=HISTORY_CLAMP_COLLECTION)[0]
            # then add it into redis
            await request.app.state.redis.set(number, json.dumps(data))
        model["data"] = data

        # model["data"]["tag"]["rpsType"] = list(set(model["data"]["tag"]["rpsType"]))
        # if None in model["data"]["tag"]["rpsType"]:
        #     model["data"]["tag"]["rpsType"].remove(None)
        # if not "hasSensor" in model["data"]["tag"]:
        #     model["data"]["tag"]["hasSensor"] = False

        model["status"] = 1
    except:
        model["status"] = 0
    return model


@deprecated_history_clamp_router.post("/v2/history_clamps", response_model=ResponseDict)
async def multiple_condition_query_history_clamps(request: Request, queryModel: MultipleConditionQueryHistoryClamps):
    """
    列表查询多条历史夹具。输入参数所有字段均可为空。

    - :param queryModel: 该对象包含isFlag, isFeature以及可为空的厂家标准standard
    - :return:
    """
    model = {"data": {"result": []}}
    result = []
    history_clamp_number_list = await request.app.state.redis.keys("202101[0-9]*")
    for i in history_clamp_number_list:
        temp_item = await request.app.state.redis.get(i)
        temp_item = json.loads(temp_item)
        result.append(temp_item)

    result = keyword_search_history_clamp(queryModel, result)
    model["data"]["total"] = len(result)
    if len(result) > 0:
        # 如果isTotal为True，意味着进入了详情页面，则不需要分页了。
        if not queryModel.isTotal:
            model["data"]["result"] = separate_page(result, page=queryModel.page, pagesize=queryModel.pagesize)
        else:
            model["data"]["result"] = result
    model["status"] = 1
    return model


@deprecated_history_clamp_router.get("/v2/history_clamps_test")
async def history_clamps_test():
    """
    ## Deprecated
    ## 测试使用索引后是否会提速。
    不行，这个太卡了。

    - :return:
    """
    data = retrieve_all_mongo_values({}, collection_name=HISTORY_CLAMP_COLLECTION)

    return data


@deprecated_history_clamp_router.put("/v2/area")
async def update_area(area: List[str]):
    """
    Deprecated.

    - :return:
    """
    updateInfo = {"$set": {"configData": {"area": area}}}
    update_mongo_value({"type": "clamp"}, updateInfo, collection_name="config")
    model = {"data": True, "status": 1}
    return model


@deprecated_history_clamp_router.post("/v2/history_clamp")
async def upload(request: Request, queryModel: UploadHistoryClampModel):
    """
    上传历史夹具的catpart格式文件并转化stp, stl, glb的接口，前端传过来的只有夹具和工件（可选）的OSS地址，这里需要在数据库里生成一条数据，把这些地址存到这条数据里。

    - :return:
    """
    number = history_clamp_number_generator()
    clampModel = generate_history_clamp_data(
        number,
        file_path=queryModel.catpartAliOssAddress,
        workpiece_file_path=queryModel.workpieceCatpartAliOssAddress,
    )

    await request.app.state.redis.set(clampModel["number"], json.dumps(clampModel))

    create_one_mongo_value(clampModel, collection_name=HISTORY_CLAMP_COLLECTION)
    send_to_message_queue(number)

    model = {"data": number, "status": 1}
    return model


@deprecated_history_clamp_router.put("/v1/history_clamp_config")
async def update_history_clamp_config(request: Request, oneInfo: UpdateHistoryClampConfigData):
    """
    更新历史夹具配置表里的信息，注意不是模型表里的。

    - :param oneInfo:
    - :return:
    """
    configData = retrieve_all_mongo_values({"type": "clamp"}, database_name=MONGO_DATABASE_NAME, collection_name="config")[0]['configData']
    if oneInfo.standard is not None:
        configData['standard'] = oneInfo.standard
    if oneInfo.area is not None:
        configData['area'] = oneInfo.area
    if oneInfo.pinType is not None:
        configData['pinType'] = oneInfo.pinType
    if oneInfo.rpsType is not None:
        configData['rpsType'] = oneInfo.rpsType
    updateInfo = {"$set": {"configData": configData}}
    update_mongo_value(
        {"type": "clamp"},
        updateInfo,
        collection_name="config",
    )

    await request.app.state.redis.set("history_clamp_config", json.dumps(configData))

    model = {"data": True, "status": 1}
    return model


@deprecated_history_clamp_router.post("/v3/history_clamps", response_model=ResponseDict)
async def multiple_condition_query_history_clamps(request: Request, queryModel: MultipleConditionQueryHistoryClamps):
    """
    ## 列表查询多条历史夹具。输入参数所有字段均可为空。
    历史夹具数据中新增了一个isSceneBinded布尔字段。

    - :param queryModel: 该对象包含isFlag, isFeature以及可为空的厂家标准standard
    - :return:
    """
    try:
        history_clamp_number_list = await request.app.state.redis.get("history_clamp")
        history_clamp_number_list = json.loads(history_clamp_number_list)
        history_clamp_list = await request.app.state.redis.mget(*history_clamp_number_list)
        result = [json.loads(i) for i in history_clamp_list]
    except:
        result = retrieve_all_mongo_values({}, collection_name=HISTORY_CLAMP_COLLECTION)
        history_clamp_number_list = [i['number'] for i in result]
        await request.app.state.redis.set("history_clamp", json.dumps(history_clamp_number_list))
        for i in result:
            await request.app.state.redis.set(i["number"], json.dumps(i))

    result = keyword_search_history_clamp(queryModel, result)
    if len(result) > 0:
        if queryModel.isSceneBinded is not None:
            result = [i for i in result if i["isSceneBinded"] == queryModel.isSceneBinded]
            total = len(result)
            result = separate_page(result, page=queryModel.page, pagesize=queryModel.pagesize)
        else:
            total = len(result)
            result = separate_page(result, page=queryModel.page, pagesize=queryModel.pagesize)
        model = {
            "data": {
                "result": result,
                "total": total,
            },
            "status": 1,
        }
    else:
        model = {"data": {}, "status": 0}
    return model


@deprecated_history_clamp_router.put("/v2/history_clamp")
async def update_history_clamp(request: Request, queryModel: UpdateHistoryClamp):
    """
    ## 更新历史夹具模型表里每个模型的Tag属性。
    - v2版，把不需要挨个判断queryModel里面的属性了。
    - 之前写的时候出了Bug，现在还是挨个判断的方法。
    - :param queryModel:
    - :return:
    """
    tag = retrieve_all_mongo_values(
        {"number": queryModel.number},
        collection_name=HISTORY_CLAMP_COLLECTION,
    )[0]['tag']
    for i in queryModel.dict().keys():
        if i == "number":
            continue
        if queryModel.dict()[i] is not None:
            tag[i] = queryModel.dict()[i]

    update_mongo_value(
        {"number": queryModel.number},
        {"$set": {"tag": tag}},
        collection_name=HISTORY_CLAMP_COLLECTION,
    )

    try:
        original_data = retrieve_one_mongo_value(queryModel.number, database_name=MONGO_DATABASE_NAME, collection_name=HISTORY_CLAMP_COLLECTION)[0]
        await request.app.state.redis.set(queryModel.number, json.dumps(original_data))
    except:
        pass

    model = {"data": True, "status": 1}
    return model


@deprecated_history_clamp_router.get("/v2/history_clamp")
async def retrieve_history_clamp_v2(request: Request, number: str):
    """
    ## 返回一条历史夹具的完整信息V2版
    返回值中多一个参数page，告知前端这条数据在第几个page（按pagesize为10的情况）。

    - :param number: 编号
    - :return:
    """
    model = {"data": {}}

    # take out the data in redis
    try:
        try:
            history_clamp = await request.app.state.redis.get(number)
            data = json.loads(history_clamp)
        except:
            # if reach here then means no data in redis. Now go to mongo.
            data = retrieve_one_mongo_value(number, database_name=MONGO_DATABASE_NAME, collection_name=HISTORY_CLAMP_COLLECTION)[0]
            # then add it into redis
            await request.app.state.redis.set(number, json.dumps(data))
            history_clamp_number_list = await request.app.state.redis.get("history_clamp")
            history_clamp_number_list = json.loads(history_clamp_number_list)
            history_clamp_number_list.append(number)
            await request.app.state.redis.set("history_clamp", json.dumps(history_clamp_number_list))
        model["data"] = data

        keys = await request.app.state.redis.get("history_clamp")
        keys = json.loads(keys)
        total_data = await request.app.state.redis.mget(*keys)
        total_data = [json.loads(i) for i in total_data]
        total_data = sorted(total_data, key=lambda x: x["name"])
        total_data = [i["number"] for i in total_data]
        model["data"]["page"], model["data"]["position"] = calculate_page(number, total_data=total_data)

        model["status"] = 1
    except:
        model["status"] = 0
    return model


@deprecated_history_clamp_router.delete("/v2/history_clamp")
async def delete_history_clamp_v2(request: Request, number: str, background_task: BackgroundTasks):
    """
    删除一套夹具数据。

    - :param number: 夹具的number
    - :return:
    """
    try:
        await request.app.state.redis.delete(number)
    except:
        pass

    model = {"data": False}
    try:
        result = delete_mongo_value(number, collection_name=HISTORY_CLAMP_COLLECTION)
        background_task.add_task(update_01)
        if result.deleted_count > 0:
            model["data"] = True
            model["status"] = 1
        else:
            model["status"] = 0
    except:
        model["status"] = 0
    return model
